/****************************************************************************
 *
 * Copyright (C) 2003-2010 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.dataset.firewall;

import nfse.NetFSERecord;
import nfse.NetFSEUtil;
import nfse.gui.record.FlexRecordField;
import nfse.gui.server.GUIRecordFactory;
import nfse.gui.server.RecordBuilderUtil;

public class PIXRecordFactory extends GUIRecordFactory<PIXRecord> {

    public PIXRecordFactory() {
        builder = new RecordBuilderUtil();
        builder.addColumn(null,"ID", RecordBuilderUtil.BIGINT);
        RecordBuilderUtil.SQLField field = builder.addColumn("Start TS","startts", RecordBuilderUtil.TIMESTAMP);
        field = builder.addColumn("Src IP","srcip", RecordBuilderUtil.INET);
        field = builder.addColumn("Src Port","srcport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Dst IP","dstip", RecordBuilderUtil.INET);
        field = builder.addColumn("Dst Port","dstport", RecordBuilderUtil.INTEGER);
        field.setSubtype(FlexRecordField.SUB_TYPE_PORT);
        field = builder.addColumn("Message","message", RecordBuilderUtil.VARCHAR,255);
    }
    
    @Override
    protected void setValues(PIXRecord record, int id) {
        int idx = -1;
        builder.setFieldValue(++idx, "" + id);
        builder.setFieldValue(++idx, "" + record.getStartTS());        
        builder.setFieldValue(++idx, record.getSrcAddr());
        builder.setFieldValue(++idx, "" + record.srcPort);
        builder.setFieldValue(++idx, record.dstAddr);
        builder.setFieldValue(++idx, "" + record.dstPort);
        builder.setFieldValue(++idx, "" + record.message);
    }

    public boolean isSyslog() {
        return true;
    }
    
    @Override
    public NetFSERecord generate(String line, int sensor) {
        PIXRecord rec = new PIXRecord(sensor);

        rec.setInitialString(line);
        line = line.trim();

        int startIdx = line.indexOf("%PIX-");
        if (startIdx == -1)
            startIdx = line.indexOf("%ASA-");

        if (startIdx == -1)
            return null;

        try {
            rec.setStartTS(NetFSEUtil.timestampFromSyslog(line));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        int messageID = Integer.parseInt(line.substring(startIdx + 7, line.indexOf(':', startIdx + 7)));
        if (messageID >= 400000 && messageID <= 400099)
            messageID = 400000;

        line = line.substring(startIdx);

        PIXParserResult result = null;
        switch (messageID) {
        case 106001:
            result = parse106001(line);
            break;
        case 106002:
            result = parse106002(line);
            break;
        case 106006:
            result = parse106006(line);
            break;
        case 106007:
            result = parse106007(line);
            break;
        case 106011:
            result = parse106011(line);
            // ystem.out.println("RESULT: " + result);
            break;
        case 106012:
            result = parse106012(line);
            break;
        case 106013:
            result = parse106013(line);
            break;
        case 106015:
            result = parse106015(line);
            break;
        case 106016:
            result = parse106016(line);
            break;
        case 106017:
            result = parse106017(line);
            break;
        case 106018:
            result = parse106018(line);
            break;
        case 106020:
            result = parse106020(line);
            break;
        case 106021:
            result = parse106021(line);
            break;
        case 106022:
            result = parse106022(line);
            break;
        case 106023:
            result = parse106023(line);
            break;
        case 107001:
            result = parse107001(line);
            break;
        case 107002:
            result = parse107002(line);
            break;
        case 108003:
            result = parse108003(line);
            break;
        case 106010:
            result = parse106010(line);
            break;
        case 106014:
            result = parse106014(line);
            break;
        case 106100:
            result = parse106100(line);
            break;
        case 109006:
            result = parse109006(line);
            break;
        case 109007:
            result = parse109007(line);
            break;
        case 109008:
            result = parse109008(line);
            break;
        case 109023:
            result = parse109023(line);
            break;
        case 109024:
            result = parse109024(line);
            break;
        case 109025:
            result = parse109025(line);
            break;
        case 201003:
            result = parse201003(line);
            break;
        case 201009:
            result = parse201009(line);
            break;
        case 201010:
            result = parse201010(line);
            break;
        case 201011:
            result = parse201011(line);
            break;
        case 202005:
            result = parse202005(line);
            break;
        case 202011:
            result = parse202011(line);
            break;
        case 303002:
            result = parse303002(line);
            break;
        case 313004:
            result = parse313004(line);
            break;
        case 305005:
            result = parse305005(line);
            break;
        case 400000:
            result = parse4000nn(line);
            break;
        case 401002:
            result = parse401002(line);
            break;
        case 401003:
            result = parse401003(line);
            break;
        case 401004:
            result = parse401004(line);
            break;
        case 410002:
            result = parse410002(line);
            break;
        case 415016:
            result = parse415016(line);
            break;
        case 416001:
            result = parse416001(line);
            break;
        case 419002:
            result = parse419002(line);
            break;
        case 450001:
            result = parse450001(line);
            break;
        case 500004:
            result = parse500004(line);
            break;
        case 302013:
            result = parse302013(line);
            break;
        case 302014:
            result = parse302014(line);
            break;
        case 302015:
            result = parse302015(line);
            break;
        case 302016:
            result = parse302016(line);
            break;
        case 304001:
            result = parse304001(line);
            break;
        case 304002:
            result = parse304002(line);
            break;
        case 415004:
            result = parse415004(line);
            break;
        case 415005:
            result = parse415005(line);
            break;
        case 415006:
            result = parse415006(line);
            break;
        case 415007:
            result = parse415007(line);
            break;
        case 415008:
            result = parse415008(line);
            break;
        case 415009:
            result = parse415009(line);
            break;
        case 415010:
            result = parse415010(line);
            break;
        case 415011:
            result = parse415011(line);
            break;
        case 415012:
            result = parse415012(line);
            break;
        case 415013:
            result = parse415013(line);
            break;
        case 415014:
            result = parse415014(line);
            break;
        case 415015:
            result = parse415015(line);
            break;
        case 415018:
            result = parse415018(line);
            break;
        case 415019:
            result = parse415019(line);
            break;
        case 415020:
            result = parse415020(line);
            break;
        case 415001:
            result = parse415001(line);
            break;
        case 415002:
            result = parse415002(line);
            break;
        case 415003:
            result = parse415003(line);
            break;
        case 415017:
            result = parse415017(line);
            break;
        case 109005:
            result = parse109005(line);
            break;
        case 109003:
            result = parse109003(line);
            break;
        case 419001:
            result = parse419001(line);
            break;
        case 421002:
            result = parse421002(line);
            break;
        case 500003:
            result = parse500003(line);
            break;
        case 500001:
            result = parse500001(line);
            break;
        case 500002:
            result = parse500002(line);
            break;
        case 305011:
            // Possible support in future version
            break;
        case 305012:
            // Possible support in future version
            break;
        default:
            // System.out.println("Unsupported message ID: " + messageID + "");
            break;
        }

        if (result == null) {
            // rec.message = line.substring(line.indexOf(startIdx, ':') +
            // 1).trim();
            rec = null;
        } else {
            rec.isAlert = result.isAlert;
            rec.setSrcAddr(result.srcIP);
            if (rec.getSrcAddr().length() > 0) {
                rec.setSrcIP(NetFSEUtil.convertIPtoLong(rec.getSrcAddr()));
            } else {
                rec.setSrcIP(-1);
            }
            rec.dstAddr = result.dstIP;
            if (rec.dstAddr.length() > 0) {
                rec.dstIP = NetFSEUtil.convertIPtoLong(rec.dstAddr);
            } else {
                rec.dstIP = -1;
            }
            rec.srcPort = result.srcPort;
            rec.dstPort = result.dstPort;
            if (result.message.length() > 0)
                rec.message = result.message;
            else
                rec.message = line.substring(line.indexOf(startIdx, ':') + 1).trim();
        }

        return rec;
    }
    
    public PIXParserResult parse106001(String line) {
        // Record of the form: %PIX|ASA-2-106001: Inbound TCP connection
        // denied from IP_address/port to IP_address/port flags tcp_flags on
        // interface interface_name
        try {
            return parseIPsAndPorts(line, 6, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106002(String line) {
        // Record of the form: %PIX|ASA-2-106002: protocol Connection denied
        // by outbound list acl_ID src inside_address dest outside_address
        try {
            return parseIPs(line, 9, 11);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106006(String line) {
        // Record of the form: %PIX|ASA-2-106006: Deny inbound UDP from
        // outside_address/outside_port to inside_address/inside_port on
        // interface interface_name.
        try {
            return parseIPsAndPorts(line, 5, 7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106007(String line) {
        // Record of the form: %PIX|ASA-2-106007: Deny inbound UDP from
        // outside_address/outside_port to inside_address/inside_port due to
        // DNS {Response|Query}.
        try {
            return parseIPsAndPorts(line, 5, 7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106010(String line) {
        // Record of the form: %PIX|ASA-3-106010: Deny inbound protocol src
        // interface_name:dest_address/dest_port dst
        // interface_name:source_address/source_port
        try {
            return parseInterfaceIPsAndPorts(line, 5, 7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106011(String line) {
        // Record of the form: %PIX|ASA-3-106011: Deny inbound (No xlate) string
        try {
            PIXParserResult result = parseInterfaceIPsAndPorts(line, 7, 9);
            NetFSEUtil.convertIPtoLong(result.srcIP);
            NetFSEUtil.convertIPtoLong(result.dstIP);
            return result;
        } catch (Exception e) {
            String[] tokens = line.split(" +");
            try {
                PIXParserResult result = new PIXParserResult();
                int srcIdx = tokens[7].indexOf(":");
                result.srcIP = tokens[7].substring(srcIdx + 1);
                NetFSEUtil.convertIPtoLong(result.srcIP);
                int dstIdx = tokens[9].indexOf(":");
                result.dstIP = tokens[9].substring(dstIdx + 1);
                NetFSEUtil.convertIPtoLong(result.dstIP);
                return result;
            } catch (Exception e2) {
                PIXParserResult result = new PIXParserResult();
                int srcIdx = tokens[8].indexOf(":");
                result.srcIP = tokens[8].substring(srcIdx + 1);
                NetFSEUtil.convertIPtoLong(result.srcIP);
                int dstIdx = tokens[10].indexOf(":");
                result.dstIP = tokens[10].substring(dstIdx + 1);
                NetFSEUtil.convertIPtoLong(result.dstIP);
                return result;
            }
        }

    }

    public PIXParserResult parse106012(String line) {
        // Record of the form: %PIX|ASA-2-106012: Deny IP from IP_address to
        // IP_address, IP options hex.
        try {
            String[] tokens = line.split(" +");
            PIXParserResult result = new PIXParserResult();
            result.dstIP = tokens[6].substring(1, tokens[6].length() - 1);
            result.srcIP = tokens[4];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106013(String line) {
        // Record of the form: %PIX|ASA-2-106013: Dropping echo request from
        // IP_address to PAT address IP_address
        try {
            String[] tokens = line.split(" +");
            PIXParserResult result = new PIXParserResult();
            result.dstIP = tokens[9];
            result.srcIP = tokens[5];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106014(String line) {
        // Record of the form: %PIX|ASA-3-106014: Deny inbound icmp src
        // interface_name: IP_address dst interface_name: IP_address (type dec,
        // code dec)
        try {
            return parseIPs(line, 6, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106015(String line) {
        // Record of the form: %PIX|ASA-6-106015: Deny TCP (no connection) from
        // IP_address/port to
        // IP_address/port flags tcp_flags on interface interface_name.
        try {
            return parseIPsAndPorts(line, 6, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106016(String line) {
        // Record of the form: %PIX|ASA-2-106016: Deny IP spoof from
        // (IP_address) to IP_address on interface interface_name.
        try {
            String[] tokens = line.split(" +");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = tokens[5].substring(1, tokens[5].length() - 1);
            result.dstIP = tokens[7];
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106017(String line) {
        // Record of the form: %PIX|ASA-2-106017: Deny IP due to Land Attack
        // from IP_address to IP_address
        try {
            PIXParserResult result = parseIPs(line, 8, 10);
            result.isAlert = true;
            return parseIPs(line, 8, 10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106018(String line) {
        // Record of the form: %PIX|ASA-2-106018: ICMP packet type ICMP_type
        // denied by outbound list acl_ID src inside_address dest
        // outside_address
        try {
            return parseIPs(line, 11, 13);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106020(String line) {
        // Record of the form: %PIX|ASA-2-106020: Deny IP teardrop fragment
        // (size = number, offset = number) from IP_address to IP_address
        try {
            PIXParserResult result = parseIPs(line, 12, 14);
            result.isAlert = true;
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // Record of the form: %PIX|ASA-1-106021: Deny protocol reverse path
    // check from source_address to dest_address on interface interface_name
    public PIXParserResult parse106021(String line) {
        try {
            return parseIPs(line, 7, 9);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106022(String line) {
        // Record of the form: %PIX|ASA-1-106022: Deny protocol connection
        // spoof from source_address to dest_address on interface
        // interface_name
        try {
            return parseIPs(line, 6, 8);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106023(String line) {
        // Record of the form: %PIX|ASA-4-106023: Deny protocol src
        // [interface_name:source_address/source_port] dst
        // interface_name:dest_address/dest_port [type {string}, code {code}] by
        // access_group acl_ID
        try {
            return parseInterfaceIPsAndPorts(line, 4, 6);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse106100(String line) {
        // Record of the form: %PIX|ASA-4-106100: access-list acl_ID {permitted
        // | denied | est-allowed} protocol
        // interface_name/source_address(source_port) ->
        // interface_name/dest_address(dest_port) hit-cnt number ({first hit |
        // number-second interval})
        try {
            String[] tokens = line.split(" +");
            String[] src = tokens[5].substring(tokens[5].indexOf("/") + 1).split("\\(");
            String[] dst = tokens[7].substring(tokens[7].indexOf("/") + 1).split("\\(");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1].substring(0, src[1].length() - 1));
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1].substring(0, dst[1].length() - 1));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse107001(String line) {
        // Record of the form: %PIX|ASA-1-107001: RIP auth failed from
        // IP_address: version=number, type=string,mode=string,
        // sequence=number on interface interface_name
        try {
            String[] tokens = line.split(" +");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = tokens[5].substring(0, tokens[5].length() - 1);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse107002(String line) {
        // Record of the form: %PIX|ASA-1-107002: RIP pkt failed from
        // IP_address: version=number on interface interface_name
        try {
            String[] tokens = line.split(" +");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = tokens[5].substring(0, tokens[5].length() - 1);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse108003(String line) {
        // Record of the form: %PIX|ASA-2-108003: Terminating ESMTP/SMTP
        // connection; malicious pattern detected in the mail address from
        // source_interface:source_address/source_port to
        // dest_interface:dest_address/dset_port. Data:string
        try {
            String[] tokens = line.split(" +");
            String[] src = tokens[12].substring(tokens[12].indexOf(":") + 1).split("/");
            String[] dst = tokens[14].substring(tokens[14].indexOf(":") + 1, tokens[14].length() - 1).split("/");
            PIXParserResult result = new PIXParserResult();
            result.isAlert = true;
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1]);
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109002(String line) {
        // Record of the form: %PIX|ASA-6-109002: Auth from
        // inside_address/inside_port to outside_address/outside_port failed
        // (server IP_address failed) on interface interface_name.
        try {
            return parseIPsAndPorts(line, 3, 5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109003(String line) {
        // Record of the form: %PIX|ASA-6-109003: Auth from inside_address to
        // outside_address/outside_port failed (all servers failed) on interface
        // interface_name.
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String[] dst = tokens[5].substring(0, tokens[5].length() - 1).split("/");
            result.srcIP = tokens[3];
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109005(String line) {
        // Record of the form: %PIX|ASA-6-109005: Authentication succeeded for
        // user user from inside_address/inside_port to
        // outside_address/outside_port on interface interface_name.
        try {
            return parseIPsAndPorts(line, 7, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109006(String line) {
        // Record of the form: %PIX|ASA-6-109006: Authentication failed for user
        // user from inside_address/inside_port to outside_address/outside_port
        // on interface interface_name.
        try {
            return parseIPsAndPorts(line, 7, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109007(String line) {
        // Record of the form: %PIX|ASA-6-109007: Authorization permitted for
        // user user from inside_address/inside_port to
        // outside_address/outside_port on interface interface_name.
        try {
            return parseIPsAndPorts(line, 7, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109008(String line) {
        // Record of the form: %PIX|ASA-6-109008: Authorization denied for user
        // user from outside_address/outside_port to inside_address/ inside_port
        // on interface interface_name.
        try {
            return parseIPsAndPorts(line, 7, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109023(String line) {
        // Record of the form: %PIX|ASA-3-109023: User from
        // source_address/source_port to dest_address/dest_port on interface
        // outside_interface must authenticate before using this service.
        try {
            return parseIPsAndPorts(line, 3, 5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109024(String line) {
        // Record of the form: %PIX|ASA-6-109024: Authorization denied from
        // source_address/source_port to dest_address/dest_port (not
        // authenticated) on interface interface_name using protocol
        try {
            return parseIPsAndPorts(line, 4, 6);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse109025(String line) {
        // Record of the form: %PIX|ASA-6-109025: Authorization denied
        // (acl=acl_ID) for user 'user' from source_address/source_port to
        // dest_address/dest_port on interface interface_name using protocol
        try {
            return parseIPsAndPorts(line, 8, 10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse201003(String line) {
        // Record of the form: %PIX|ASA-2-201003: Embryonic limit exceeded
        // nconns/elimit for outside_address/outside_port (global_address)
        // inside_address/inside_port on interface interface_name
        try {
            return parseIPsAndPorts(line, 6, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse201009(String line) {
        // Record of the form: %PIX|ASA-3-201009: TCP connection limit of number
        // for host IP_address on interface_name exceeded
        try {
            return parseIPs(line, 8, -1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse201010(String line) {
        // Record of the form: %PIX|ASA-3-201010: Embryonic connection limit
        // exceeded econns/limit for dir packet from source_address/source_port
        // to dest_address/dest_port on interface interface_name
        try {
            return parseIPsAndPorts(line, 10, 12);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse201011(String line) {
        // Record of the form: %PIX|ASA-3-201011: Connection limit exceeded
        // cnt/limit for dir packet from sip/sport to dip/dport on interface
        // if_name
        try {
            return parseIPsAndPorts(line, 9, 11);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse202005(String line) {
        // Record of the form: %PIX|ASA-3-202005: Non-embryonic in embryonic
        // list outside_address/outside_port inside_address/inside_port
        try {
            return parseIPsAndPorts(line, 5, 6);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse202011(String line) {
        // Record of the form: %PIX|ASA-3-202011: Connection limit exceeded
        // econns/limit for dir packet from source_address/source_port to
        // dest_address/dest_port on interface interface_name
        try {
            return parseIPsAndPorts(line, 9, 11);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse302013(String line) {
        // Record of the form: %PIX|ASA-6-302013: Built {inbound|outbound} TCP
        // connection number for
        // interface_name:real_address/real_port (mapped_address/mapped_port) to
        // interface_name:real_address/real_port (mapped_address/mapped_port)
        // [(user)]
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String srcStr = tokens[7];
            int colIdx = srcStr.indexOf(':');
            int slashIdx = srcStr.indexOf('/');
            result.srcIP = srcStr.substring(colIdx + 1, slashIdx);
            result.srcPort = Integer.parseInt(srcStr.substring(slashIdx + 1));

            String dstStr = tokens[10];
            colIdx = dstStr.indexOf(':');
            slashIdx = dstStr.indexOf('/');
            result.dstIP = dstStr.substring(colIdx + 1, slashIdx);
            result.dstPort = Integer.parseInt(dstStr.substring(slashIdx + 1));

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse302014(String line) {
        // Record of the form: %PIX|ASA-6-302014: Teardown TCP connection number
        // for
        // interface_name:real_address/real_port to
        // interface_name:real_address/real_port
        // duration time bytes number [reason] [(user)]
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String srcStr = tokens[6];
            int colIdx = srcStr.indexOf(':');
            int slashIdx = srcStr.indexOf('/');
            result.srcIP = srcStr.substring(colIdx + 1, slashIdx);
            result.srcPort = Integer.parseInt(srcStr.substring(slashIdx + 1));

            String dstStr = tokens[8];
            colIdx = dstStr.indexOf(':');
            slashIdx = dstStr.indexOf('/');
            result.dstIP = dstStr.substring(colIdx + 1, slashIdx);
            result.dstPort = Integer.parseInt(dstStr.substring(slashIdx + 1));

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse302015(String line) {
        // Record of the form: %PIX|ASA-6-302015: Built {inbound|outbound} UDP
        // connection number for
        // interface_name:real_address/real_port (mapped_address/mapped_port) to
        // interface_name:real_address/real_port (mapped_address/mapped_port)
        // [(user)]
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String srcStr = tokens[7];
            int colIdx = srcStr.indexOf(':');
            int slashIdx = srcStr.indexOf('/');
            result.srcIP = srcStr.substring(colIdx + 1, slashIdx);
            result.srcPort = Integer.parseInt(srcStr.substring(slashIdx + 1));

            String dstStr = tokens[10];
            colIdx = dstStr.indexOf(':');
            slashIdx = dstStr.indexOf('/');
            result.dstIP = dstStr.substring(colIdx + 1, slashIdx);
            result.dstPort = Integer.parseInt(dstStr.substring(slashIdx + 1));

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse302016(String line) {
        // Record of the form: %PIX|ASA-6-302016: Teardown UDP connection number
        // for
        // interface_name:real_address/real_port to
        // interface_name:real_address/real_port
        // duration time bytes number [(user)]
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String srcStr = tokens[6];
            int colIdx = srcStr.indexOf(':');
            int slashIdx = srcStr.indexOf('/');
            result.srcIP = srcStr.substring(colIdx + 1, slashIdx);
            result.srcPort = Integer.parseInt(srcStr.substring(slashIdx + 1));

            String dstStr = tokens[8];
            colIdx = dstStr.indexOf(':');
            slashIdx = dstStr.indexOf('/');
            result.dstIP = dstStr.substring(colIdx + 1, slashIdx);
            result.dstPort = Integer.parseInt(dstStr.substring(slashIdx + 1));

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse303002(String line) {
        // Record of the form: %PIX|ASA-6-303002: source_address
        // {Stored|Retrieved} dest_address:
        // mapped_address
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            result.srcIP = tokens[1];
            result.dstIP = tokens[3].substring(0, tokens[3].indexOf(":"));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse304001(String line) {
        // Record of the form: %PIX|ASA-5-304001: user source_address Accessed
        // {JAVA URL|URL} dest_address:url
        try {
            line = line.replaceAll("JAVA URL", "JAVA_URL");
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            result.srcIP = tokens[1];
            String[] tokens2 = tokens[4].split(":");
            result.dstIP = tokens2[0];
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse304002(String line) {
        // Record of the form: %PIX|ASA-5-304002: Access denied URL chars SRC
        // IP_address DEST IP_address: chars
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            result.srcIP = tokens[6];
            result.dstIP = tokens[8].substring(0, tokens[8].length() - 1);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse305005(String line) {
        // Record of the form: %PIX|ASA-3-305005: No translation group found for
        // protocol src
        // interface_name:dest_address/dest_port dst
        // interface_name:source_address/source_port
        try {
            return parseInterfaceIPsAndPorts(line, 8, 10);
        } catch (Exception e) {
            System.out.println(line);
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse313004(String line) {
        // Record of the form: %PIX|ASA-4-313004: Denied ICMP type=icmp_type,
        // from source_address on interface interface_name to dest_address: no
        // matching session
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            result.srcIP = tokens[5];
            result.dstIP = tokens[10].substring(0, tokens[10].length() - 1);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse4000nn(String line) {
        // Record of the form: %PIX|ASA-4-4000nn: IPS:number string from
        // IP_address to IP_address on interface interface_name
        try {
            String[] tokens = line.split(" +");

            PIXParserResult result = parseIPs(line, tokens.length - 6, tokens.length - 4);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse401002(String line) {
        // Record of the form: %PIX|ASA-4-401002: Shun added: IP_address
        // IP_address port port
        try {
            return parseIPs(line, 3, -1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse401003(String line) {
        // Record of the form: %PIX|ASA-4-401003: Shun deleted: IP_address
        try {
            return parseIPs(line, 3, -1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse401004(String line) {
        // Record of the form: %PIX|ASA-4-401004: Shunned packet: IP_address ==>
        // IP_address on interface interface_name
        try {
            return parseIPs(line, 3, 5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse410002(String line) {
        // Record of the form: %PIX|ASA-2-410002: Dropped num DNS responses with
        // mis-matched id in the past sec second(s): from src_ifc:sip/sport to
        // dest_ifc:dip/dport
        try {
            return parseInterfaceIPsAndPorts(line, 14, 16);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415001(String line) {
        // Record of the form: %PIX|ASA-6-415001: HTTP - matched matched_string
        // in policy-map map_name, header field count exceeded connection_action
        // from int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 14, 16);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415002(String line) {
        // Record of the form: %PIX|ASA-6-415002: HTTP - matched matched_string
        // in policy-map map_name, header field length exceeded
        // connection_action from int_type:IP_address/port_num to
        // int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 14, 16);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415003(String line) {
        // Record of the form: %PIX|ASA-6-415003: HTTP - matched matched_string
        // in policy-map map_name, body length exceeded connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 13, 15);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415004(String line) {
        // Record of the form: %PIX|ASA-5-415004: HTTP - matched matched_string
        // in policy-map map_name, content-type verification failed
        // connection_action from int_type:IP_address/port_num to
        // int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 13, 15);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415005(String line) {
        // Record of the form: %PIX|ASA-5-415005: HTTP - matched matched_string
        // in policy-map map_name, URI length exceeded connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 13, 15);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415006(String line) {
        // Record of the form: %PIX|ASA-5-415006: HTTP - matched matched_string
        // in policy-map map_name, URI matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num

        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415007(String line) {
        // Record of the form: %PIX|ASA-5-415007: HTTP - matched matched_string
        // in policy-map map_name, Body matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415008(String line) {
        // Record of the form: %PIX|ASA-5-415008: HTTP - matched matched_string
        // in policy-map map_name, header matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415009(String line) {
        // Record of the form: %PIX|ASA-5-415009: HTTP - matched matched_string
        // in policy-map map_name, method matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415010(String line) {
        // Record of the form: %PIX|ASA-5-415010: matched matched_string in
        // policy-map map_name, transfer encoding matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 11, 13);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415011(String line) {
        // Record of the form: %PIX|ASA-5-415011: HTTP - policy-map
        // map_name:Protocol violation connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 8, 10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415012(String line) {
        // Record of the form: %PIX|ASA-5-415012: HTTP - matched matched_string
        // in policy-map map_name, Unknown mime-type connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415013(String line) {
        // Record of the form: %PIX|ASA-5-415013: HTTP - policy-map
        // map-name:Malformed chunked encoding connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 9, 11);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415014(String line) {
        // Record of the form: %PIX|ASA-5-415014: HTTP - matched matched_string
        // in policy-map map_name, Mime-type in response wasn't found in the
        // accept-types of the request connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 21, 23);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415015(String line) {
        // Record of the form: %PIX|ASA-5-415015: HTTP - matched matched_string
        // in policy-map map_name, transfer-encoding unknown connection_action
        // from int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 12, 14);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415016(String line) {
        // Record of the form: %PIX|ASA-4-415016: policy-map map_name:Maximum
        // number of unanswered HTTP requests exceeded connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 11, 13);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415017(String line) {
        // Record of the form: %PIX|ASA-6-415017: HTTP - matched_string in
        // policy-map map_name, arguments matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 11, 13);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415018(String line) {
        // Record of the form: %PIX|ASA-5-415018: HTTP - matched matched_string
        // in policy-map map_name, Header length exceeded connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 13, 15);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415019(String line) {
        // Record of the form: %PIX|ASA-5-415019: HTTP - matched matched_string
        // in policy-map map_name, status line matched connection_action from
        // int_type:IP_address/port_num to int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 13, 15);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse415020(String line) {
        // Record of the form: %PIX|ASA-5-415020: HTTP - matched matched_string
        // in policy-map map_name, a non-ASCII character was matched
        // connection_action from int_type:IP_address/port_num to
        // int_type:IP_address/port_num
        try {
            return parseInterfaceIPsAndPorts(line, 15, 17);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse416001(String line) {
        // Record of the form: %PIX|ASA-4-416001: Dropped UDP SNMP packet from
        // source_interface:source_IP/source_port to
        // dest_interface:dest_address/dest_port; version (prot_version) is not
        // allowed through the firewall
        try {
            String[] tokens = line.split(" +");
            String[] src = tokens[6].substring(tokens[6].indexOf(":") + 1).split("/");
            String[] dst = tokens[8].substring(tokens[8].indexOf(":") + 1, tokens[8].length() - 1).split("/");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1]);
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse419001(String line) {
        // Record of the form: %PIX|ASA-4-419001: Dropping TCP packet from
        // src_ifc:src_IP/src_port to dest_ifc:dest_IP/dest_port, reason: MSS
        // exceeded, MSS size, data size
        try {
            String[] tokens = line.split(" +");
            String[] src = tokens[5].substring(tokens[5].indexOf(":") + 1).split("/");
            String[] dst = tokens[7].substring(tokens[7].indexOf(":") + 1, tokens[7].length() - 1).split("/");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1]);
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse419002(String line) {
        // Record of the form: %ASA-4-419002: Received duplicate TCP SYN from
        // in_interface:src_address/src_port to
        // out_interface:dest_address/dest_port with different initial sequence
        // number.
        try {
            return parseInterfaceIPsAndPorts(line, 6, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse421002(String line) {
        // Record of the form: %ASA-6-421002: TCP|UDP flow from
        // interface_name:IP_address/port to interface_nam:IP_address/port
        // bypassed application checking because the protocol is not supported.
        try {
            return parseInterfaceIPsAndPorts(line, 4, 6);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse450001(String line) {
        // Record of the form: %ASA-4-450001: Deny traffic for protocol
        // protocol_id src interface_name:IP_address/port dst
        // interface_name:IP_address/port, licensed host limit of num exceeded.
        try {
            String[] tokens = line.split(" +");
            String[] src = tokens[7].substring(tokens[7].indexOf(":") + 1).split("/");
            String[] dst = tokens[9].substring(tokens[9].indexOf(":") + 1, tokens[9].length() - 1).split("/");
            PIXParserResult result = new PIXParserResult();
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1]);
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse500001(String line) {
        // Record of the form: %PIX|ASA-5-500001: ActiveX content modified src
        // IP_address dest IP_address on interface interface_name.
        try {
            return parseIPs(line, 5, 7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse500002(String line) {
        // Record of the form: %PIX|ASA-5-500002: Java content modified src
        // IP_address dest IP_address on interface interface_name.
        try {
            return parseIPs(line, 5, 7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse500003(String line) {
        // Record of the form: %PIX|ASA-5-500003: Bad TCP hdr length
        // (hdrlen=bytes, pktlen=bytes) from source_address/source_port to
        // dest_address/dest_port, flags: tcp_flags, on interface interface_name
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");
            String[] src = tokens[8].split("/");
            String[] dst = tokens[10].substring(0, tokens[10].length() - 1).split("/");
            result.srcIP = src[0];
            result.dstIP = dst[0];
            result.srcPort = Integer.parseInt(src[1]);
            result.dstPort = Integer.parseInt(dst[1]);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse500004(String line) {
        // Record of the form: %PIX|ASA-4-500004: Invalid transport field for
        // protocol=protocol, from source_address/source_port to
        // dest_address/dest_port
        try {
            return parseIPsAndPorts(line, 7, 9);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parse710003(String line) {
        // Record of the form: %PIX|ASA-3-710003: {TCP|UDP} access denied by ACL
        // from
        // source_address/source_port to interface_name:dest_address/service
        try {
            PIXParserResult result = new PIXParserResult();
            String[] tokens = line.split(" +");

            int slashIdx = tokens[7].indexOf("/");
            result.srcIP = tokens[7].substring(0, slashIdx);
            result.srcPort = Integer.parseInt(tokens[7].substring(slashIdx + 1));

            slashIdx = tokens[9].indexOf("/");
            int colIdx = tokens[9].indexOf(":");
            result.dstIP = tokens[9].substring(colIdx + 1, slashIdx);
            result.dstPort = Integer.parseInt(tokens[9].substring(slashIdx + 1));

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public PIXParserResult parseInterfaceIPsAndPorts(String line, int srcIdx, int dstIdx) throws Exception {
        // try {

        String[] tokens = line.split(" +");
        PIXParserResult result = new PIXParserResult();
        try {
            if (srcIdx != -1) {
                String[] src = tokens[srcIdx].substring(tokens[srcIdx].indexOf(":") + 1).split("/");
                result.srcIP = src[0];
                result.srcPort = Integer.parseInt(src[1]);
            }
            if (dstIdx != -1) {
                String[] dst = tokens[dstIdx].substring(tokens[dstIdx].indexOf(":") + 1).split("/");
                result.dstIP = dst[0];
                result.dstPort = Integer.parseInt(dst[1]);
            }
            return result;
        } catch (Exception e) {
            if (srcIdx != -1) {
                result.srcIP = tokens[srcIdx].substring(tokens[srcIdx].indexOf(":") + 1);
            }
            if (dstIdx != -1) {
                result.dstIP = tokens[dstIdx].substring(tokens[dstIdx].indexOf(":") + 1);
            }
            return result;
        }

    }

    public PIXParserResult parseIPs(String line, int srcIPIdx, int dstIPIdx) throws Exception {

        PIXParserResult result = new PIXParserResult();
        String[] tokens = line.split(" +");
        if (srcIPIdx != -1)
            result.srcIP = tokens[srcIPIdx];
        if (dstIPIdx != -1)
            result.dstIP = tokens[dstIPIdx];
        return result;

    }

    public PIXParserResult parseIPsAndPorts(String line, int srcIdx, int dstIdx) throws Exception {

        PIXParserResult result = new PIXParserResult();
        String[] tokens = line.split(" +");
        if (srcIdx != -1) {
            String[] src = tokens[srcIdx].split("/");
            result.srcIP = src[0];
            result.srcPort = Integer.parseInt(src[1]);
        }
        if (dstIdx != -1) {
            String[] dst = tokens[dstIdx].split("/");
            result.dstIP = dst[0];
            result.dstPort = Integer.parseInt(dst[1]);
        }
        return result;

    }

    @Override
    public NetFSERecord generate() {
        return new PIXRecord();
    }
    
    protected class PIXParserResult {
        public String dstIP = "";

        public int dstPort = -1;

        public String message = "";

        public String srcIP = "";

        public int srcPort = -1;
        
        public boolean isAlert = false;

        public String toString() {
            return srcIP + ":" + srcPort + "->" + dstIP + ":" + dstPort;
        }
    }

}
